Unterprogramme dienen dazu, Programmcode übersichtlicher und weniger repetitiv zu machen, indem Teile eines Programms in besagte Unterprogramme ausgelagert werden.
Hier sind einige Eigenschaften von Unterprogrammen:
Doch was sind Unterprogramme? Unterprogramme können Code enthalten und diesen Ausführen, wenn das Unterprogramm aufgerufen wird. Man stelle sich vor, man hat ein
Programm, das eine gewisse Menge an immer gleichem Code an verschiedenen Stellen ausführen:
Hier müsste man den selben Code zwei mal hinschreiben, was eher umständlich ist. Zudem müsste man wenn man das Stück Code ändern möchte, es zwei mal bearbeiten.
Die Lösung dazu sind Unterprogramme:
Und voilà, sehr viel eleganter. Der doppelt vorkommende Code wurde in ein anderes Unterprogramm verschoben. Doch was genau ist da jetzt passiert? Schauen wir uns das genauer an.
Es gibt bei einem Unterprogramm einmal die Definition und einmal die Aufrufe des Unterprogramms. Sagen wir, wir haben ein Unterprogramm gibAus
was ein eindimensionales Feld ausgeben soll:
Dies ist die Definition des Unterprogramms. In ihm wird definiert, was passieren soll, wenn das Unterprogramm aufgerufen wird. Die erste Zeile des Unterprogramms,
also public void gibAus(String[] meinFeld)
in diesem Fall, nennt sich Signatur. Die Signatur des Unterprogramms gibt relativ viele Informationen:
Name | Erklärung | Mögliche Werte |
---|---|---|
Sichtbarkeit | Die Sichtbarkeit beschreibt, von wo aus das Unterprogramm aus aufgerufen werden kann.public macht, dass jeder, der auf ein Objekt der Klasse zugriff hat, darauf zugreifen kann.private bedeutet, dass nur das Objekt selbst es aufrufen kann.protected heißt, dass nur das Objekt selbst und davon erbende Klassen es aufrufen können. |
public private protected |
Rückgabetyp | Jedes Unterprogramm kann einem einen Wert zurückgeben, nachdem es ausgeführt wurde. Der Rückgabetyp beschreibt den Typ des Wertes, der zurückgegeben werden soll. Wenn ein Unterprogramm keinen Wert zurückgeben soll, muss als Rückgabetyp void verwendet werden. Wenn aber etwas anderes da steht, z.B. String , dann muss auch ein Wert von diesem Typ zurückgegeben werden. Dies passiert mit return . |
void String int ... |
Name | Schlicht gesagt: Der Name des Unterprogramms. Für ihn gelten die gleichen Regeln wie für Variablen. Dieser wird später auch beim Unterprogrammaufruf verwendet. |
meinUnterprogramm gibAus berechneWerte ... |
Parameterliste | Eine beliebig lange Liste an Werten, die dem Unterprogramm beim Aufruf mitgegeben werden müssen. Die einzelnen Parameter werden durch , getrennt und haben zuerst den Typ und dann den Bezeichner. Sie stehen in den Klammern des Unterprogramms. |
String text, int wert |
Also, das Unterprogramm public void gibAus(String[] meinFeld)
von oben hat die Sichtbarkeit public
(kann also von überall aus aufgerufen werden), gibt keinen Wert
zurück (void
) und nimmt einen Parameter, ein String Array (String[]
), das es dann meinFeld
nennt. Hier die einzelnen Teile im Detail:
Ein Parameter eines Unterprogramms ist das, was man beim Unterprogrammaufruf mitgeben kann. Hier ein Beispiel:
Wenn man in dem Beispiel die main
ausführen würde, würde (1) Thomas
und (2) Yan
ausgegeben werden. Warum?
Das Unterprogramm printCombined
nimmt zwei Parameter an: einen integer (id
) und einen Text (username
). Der erste Unterprogrammaufruf printCombined(1, "Thomas");
nimmt direkt als Parameter an: 1, "Thomas"
. Diese Werte werden dann den Variablen id
und username
unten im Unterprogramm eingesetzt. Das heißt, id = 1
und
username = "Thomas"
. Sobald das Unterprogramm fertig abgelaufen ist, kehrt das Programm zum Aufruf zurück.
Als nächstes haben wir zwei Variablen meineID
und name
. Ihnen sind die Werte 2
und "Yan"
zugeordnet. Das heißt, hier werden dann die Werte der Variablen
als Parameter mitgegeben und es wird im Unterprogramm (2) Yan
ausgegeben.
Parameter sind also nichts anderes als Werte, die beim Aufruf an das Unterprogramm übergeben werden können.
Bei der Parameterübergabe gibt es allerdings zwei unterschiedliche Fälle: Call by value und call by reference. Diese beiden wurden bereits bei den
Feldern angedeutet.
Call by value
Bei call by value wird ein Wert als Parameter an das Unterprogramm übergeben. Dies trifft auf alle primitiven Datentypen zu, also alle, die klein geschrieben werden
(int
, char
). Hierbei wird also der Wert kopiert und diese Kopie des Wertes an das Unterprogramm übergeben.
Wenn also in diesem Beispiel meinWert
mit dem Wert von 10
an doStuff
übergeben wird, so wird eine Kopie des Wertes 10
erstellt und in die Variable meinParameter
gepackt. Wenn diese Kopie (meinParameter
) verändert wird, bleibt das original (meinWert
) unverändert.
Wie im Bild zu sehen ist, wurde der Wert an eine andere Adresse im Speicher kopiert und beide Variablen haben somit eine eigene Kopie des Wertes.
Call by reference
Bei call by Reference wird nicht der Wert der angegebenen Variable mitgegeben, sondern die Referenz, also ein Zeiger, zum eigentlichen Wert mitgegeben. Hier sind
das alle restlichen Typen, also Objekte und Felder.
Bei dem Übergebenen Wert handelt es sich also tatsächlich um den exakt gleichen Wert, nicht bloß eine Kopie davon. Wenn man den Wert der Variable dann im
Unterprogramm verändert, so verändert sich auch der originale Wert der originalen Variable.
In diesem Beispiel wird ein Feld int[] meinFeld
mitgegeben (also kein primitiver Datentyp). Es wird hierbei also keine Kopie angefertigt, es ist noch immer das
gleiche Feld wie oben. Wenn es also dort verändert wird: meinParameter[0] = 453
, dann wird es auch oben verändert und der Wert bei 0
ist nicht mehr 10
,
sondern 453
. Es würde also zwei mal 453
ausgegeben werden.
Es handelt sich um ein und dasselbe Objekt.
Ein Unterprogramm kann einem auch Werte zurückgeben. Dieser wird, wie oben beschrieben, ebenfalls in der Signatur des Unterprogramms angegeben.
Wenn man nicht möchte, dass das Unterprogramm einem einen Wert zurückgibt, muss man als Rückgabetyp void
angeben.
Zurückgegeben wird in einem Unterprogramm mit return ...;
, wobei der zurückzugebende Wert hinter dem return
angegeben wird. Sobald das Unterprogramm auf ein return
stößt,
verlässt es sofort das Unterprogramm, es ist also immer das letzte, was man in einem Unterprogramm tut. Der angegebene Wert muss von dem Typ sein, der oben in der Signatur des
Unterprogramms angegeben ist, ansonsten gibt es einen Kompilierfehler.
Es kann auch mehrere return
-Anweisungen im Programm geben:
In diesem Beispiel würde 0
, 60
und 74
ausgegeben werden. Beim berechne(12, 2)
verlässt es das Unterprogramm beim zweiten return
, bei berechne(3, 8)
beim ersten und bei
berechne(20, 34)
beim letzten. Wie zu erwarten springt das Programm sobald es auf das return
stößt zurück zum Unterprogrammaufruf und setzt anstelle des Aufrufs den zurückgegebenen
Wert ein, also steht in main
eigentlich das hier:
Basierend auf dem Rückgabewert-Typ wird auch die Namensgebung bestimmt:
void
), nennt man es Prozedur
Je nachdem, ob der Parameter in der Unterprogrammdefinition oder im Aufruf steht, wird er unterschiedlich benannt.
Die Parameter in der Definition eines Unterprogramms (also in der Signatur) werden Formalparameter genannt. In diesem Beispiel hier wäre also String textParameter
ein
Formalparameter, da es sich bei dem Code um eine Unterprogrammdefinition handelt:
Wenn nun das Unterprogramm aufgerufen wird, so werden für die benötigten Parameter konkrete Werte eingesetzt. Das sind dann die Aktualparameter. Die beiden hier
konkreten mitgegebenen Werte sind also Aktualparameter:
Frage 1
Wie werden bei einem Unterprogramm Parameter angegeben?
Frage 2
Was für mögliche Rückgabewerte gibt es für ein Unterprogramm? Wie nennt man dann je das Unterprogramm?
Frage 3
Was ist der Unterschied zwischen call by value und call by reference?
Frage 4
Im Beispiel oben, was würde berechne(56, 3)
, berechne(2, 6)
und berechne(5, 10)
zurückgeben?
Frage 5
Erstelle ein Unterprogramm, das einen Text als Parameter erhält und den doppelten Ganzzahlwert zurückgibt. Erstelle drei Aufrufe und deren Rückgaben dafür.
Frage 6
Extrahiere sinnvoll Unterprogramme aus dem Programm unten:
Frage 7
Liste alle Aktual-/Formalparameter im Code hier drunter auf:
Frage 8
Denk dir selbst ein Unterprogramm aus, das irgendetwas tut, was sich lohnt auszulagern und du z.B. immer mal wieder gebrauchen könntest!